<template>
  <div class="dv-conical-chart" :class="{ 'is-dark': isDark }">
    <svg :width="size" :height="size" viewBox="0 0 100 100">
      <defs>
        <linearGradient :id="`conical-gradient-${uid}`" x1="0%" y1="0%" x2="0%" y2="100%">
          <stop offset="0%" :stop-color="color" stop-opacity="1" />
          <stop offset="100%" :stop-color="color" stop-opacity="0.3" />
        </linearGradient>
      </defs>
      
      <!-- 圆锥底部 -->
      <ellipse
        cx="50"
        cy="80"
        rx="30"
        ry="8"
        :fill="color"
        opacity="0.3"
      />
      
      <!-- 圆锥体 -->
      <path
        :d="conicalPath"
        :fill="`url(#conical-gradient-${uid})`"
        :stroke="color"
        stroke-width="0.5"
      />
      
      <!-- 顶部圆 -->
      <ellipse
        cx="50"
        :cy="topY"
        :rx="topRadius"
        :ry="topRadius * 0.3"
        :fill="color"
        opacity="0.8"
      />
      
      <!-- 百分比文字 - 上方 -->
      <text
        x="50"
        y="40"
        text-anchor="middle"
        dominant-baseline="middle"
        :fill="textColor"
        font-size="8"
        font-weight="bold"
        class="percentage-text"
      >
        {{ displayValue }}%
      </text>
      
      <!-- 标题文字 - 下方 -->
      <text
        x="50"
        y="60"
        text-anchor="middle"
        dominant-baseline="middle"
        :fill="textColor"
        font-size="3.5"
        opacity="0.7"
      >
        {{ title }}
      </text>
    </svg>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { useSettingsStore } from '@/store'
import { ThemeEnum } from '@/enums/ThemeEnum'

interface Props {
  value: number
  size?: number
  color?: string
  title?: string
}

const props = withDefaults(defineProps<Props>(), {
  size: 120,
  title: ''
})

const settingsStore = useSettingsStore()
const isDark = computed(() => settingsStore.theme === ThemeEnum.DARK)

const currentValue = ref(0)
const uid = ref(`conical-${Math.random().toString(36).substr(2, 9)}`)

const color = computed(() => {
  if (props.color) return props.color
  return isDark.value ? '#00d4ff' : '#409eff'
})

const textColor = computed(() => isDark.value ? '#fff' : '#303133')

const displayValue = computed(() => Math.round(currentValue.value))

const topY = computed(() => {
  const minY = 20
  const maxY = 80
  return maxY - (currentValue.value / 100) * (maxY - minY)
})

const topRadius = computed(() => {
  const minRadius = 5
  const maxRadius = 30
  return minRadius + (currentValue.value / 100) * (maxRadius - minRadius)
})

const conicalPath = computed(() => {
  const bottomY = 80
  const bottomRx = 30
  const ty = topY.value
  const tr = topRadius.value
  
  return `
    M ${50 - tr} ${ty}
    L ${50 - bottomRx} ${bottomY}
    A ${bottomRx} 8 0 0 0 ${50 + bottomRx} ${bottomY}
    L ${50 + tr} ${ty}
    A ${tr} ${tr * 0.3} 0 0 1 ${50 - tr} ${ty}
    Z
  `
})

watch(() => props.value, (newVal) => {
  const start = currentValue.value
  const target = Math.min(Math.max(newVal, 0), 100)
  const duration = 1000
  const startTime = Date.now()
  
  const animate = () => {
    const now = Date.now()
    const progress = Math.min((now - startTime) / duration, 1)
    const easeOut = 1 - Math.pow(1 - progress, 3)
    
    currentValue.value = start + (target - start) * easeOut
    
    if (progress < 1) {
      requestAnimationFrame(animate)
    }
  }
  
  requestAnimationFrame(animate)
}, { immediate: true })
</script>

<style lang="scss" scoped>
.dv-conical-chart {
  display: inline-block;
  filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.1));
  
  svg {
    display: block;
    
    .percentage-text {
      font-family: 'DS-Digital', 'Courier New', monospace;
      font-weight: bold;
    }
    
    path, ellipse {
      transition: all 0.3s;
    }
  }
  
  &.is-dark {
    filter: drop-shadow(0 0 10px rgba(0, 212, 255, 0.3));
    
    .percentage-text {
      text-shadow: 0 0 10px currentColor;
    }
  }
}
</style>
